package com.lyh.system.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import com.lyh.common.core.domain.AjaxResult;
import com.lyh.common.core.domain.entity.SysUser;
import com.lyh.common.enums.*;
import com.lyh.common.exception.ServiceException;
import com.lyh.common.utils.CommonUtils;
import com.lyh.common.utils.SecurityUtils;
import com.lyh.common.utils.StringUtils;
import com.lyh.system.biz.IOrderBiz;
import com.lyh.system.biz.IPayBiz;
import com.lyh.system.domain.*;
import com.lyh.system.domain.req.OrderAddrReq;
import com.lyh.system.domain.req.OrderNoAddrReq;
import com.lyh.system.domain.req.OrderWLReq;
import com.lyh.system.domain.req.OrderWebReq;
import com.lyh.system.domain.resp.OrderWebResq;
import com.lyh.system.domain.vo.BuyGoodsVo;
import com.lyh.system.domain.vo.PayVo;
import com.lyh.system.mapper.*;
import com.lyh.system.service.IGoodsService;
import lombok.extern.log4j.Log4j2;
import org.jetbrains.annotations.Nullable;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.lyh.system.service.IOrderService;
import org.springframework.transaction.annotation.Transactional;

import static com.lyh.common.enums.PaymentMethodEnum.*;

/**
 * 订单Service业务层处理
 *
 * @author ruoyi
 * @date 2023-05-11
 */
@Service
@Log4j2
public class OrderServiceImpl implements IOrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private GoodsMapper goodsMapper;
    @Autowired
    private IGoodsService goodsService;
    @Autowired
    private AssetMapper assetMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private OperationInfoMapper operationInfoMapper;
    @Autowired
    private ReceiveAddressMapper receiveAddressMapper;

    @Autowired
    private IOrderBiz orderBiz;

    /**
     * 查询订单
     *
     * @param id 订单主键
     * @return 订单
     */
    @Override
    public Order selectOrderById(Long id) {
        return orderMapper.selectOrderById(id);
    }

    /**
     * 查询订单列表
     *
     * @param order 订单
     * @return 订单
     */
    @Override
    public List<Order> selectOrderList(Order order) {
        return orderMapper.selectOrderList(order);
    }

    /**
     * 新增订单
     *
     * @param order 订单
     * @return 结果
     */
    @Override
    public int insertOrder(Order order) {
        //查找收获地址
        return orderMapper.insertOrder(order);
    }

    /**
     * 修改订单
     *
     * @param order 订单
     * @return 结果
     */
    @Override
    public int updateOrder(Order order) {
        return orderMapper.updateOrder(order);
    }

    /**
     * 批量删除订单
     *
     * @param ids 需要删除的订单主键
     * @return 结果
     */
    @Override
    public int deleteOrderByIds(Long[] ids) {
        return orderMapper.deleteOrderByIds(ids);
    }

    /**
     * 删除订单信息
     *
     * @param id 订单主键
     * @return 结果
     */
    @Override
    public int deleteOrderById(Long id) {
        return orderMapper.deleteOrderById(id);
    }

    @Override
    public List<OrderWebResq> selectOrderListByWeb(OrderWebReq req) {

        List<OrderWebResq> orderWebResqs = orderMapper.webPagelist(req);
        if (orderWebResqs != null && orderWebResqs.size() > 0) {

            orderWebResqs.stream().forEach(c -> {
                c.setStatusName(c.getStatus().getMsg());
                if(StringUtils.isNotEmpty(c.getPaymentMethod())){
                    c.setPaymentMethodName(PaymentMethodEnum.valueOf(c.getPaymentMethod()).getTitle());
                }
            });
        }
        return orderWebResqs;
    }

    @Override
    public int editLogistics(OrderWLReq req) {
        Order order = orderMapper.selectById(req.getId());
        order.setLogisticsCompany(req.getLogisticsCompany());
        order.setLogisticsNum(req.getLogisticsNum());
        order.setStatus("alrealy_send");
        return orderMapper.updateById(order);
    }

    @Override
    public int editAddress(OrderAddrReq req) {
        Order order = orderMapper.selectById(req.getId());
        if (StringUtils.isNotEmpty(req.getLogisticsInfo())) {
            order.setLogisticsInfo(req.getLogisticsInfo());
        }
        if (req.getActualPayment() != null) {
            order.setActualPayment(req.getActualPayment());
        }
        return orderMapper.updateById(order);
    }

    /**
     * @description: 无物流
     * @author: ljx
     * @date: 2023/6/2 0:35
     * @param: [req]
     * @return: int
     **/
    @Override
    public int noAddress(OrderNoAddrReq req) {
        Order order = orderMapper.selectById(req.getId());
        order.setStatus("success");
        order.setLogisticsNum("无物流");
        return orderMapper.updateById(order);
    }

    /**
     * @description: 退款成功
     * @author: ljx
     * @date: 2023/6/2 0:39
     * @param: [req]
     * @return: com.lyh.common.core.domain.AjaxResult
     **/
    @Override
    public AjaxResult refundOrder(OrderNoAddrReq req) {

        Order order = orderMapper.selectById(req.getId());
        String paymentMethod = order.getPaymentMethod();
        if (paymentMethod.equals(PaymentMethodEnum.ALIPAY.name())) {
            String s = payBiz.zfbRefund(order);
            if (s.equals(StoreOrderStatusEnum.refund_success.name())) {
                return AjaxResult.success(StoreOrderStatusEnum.refund_success.name());
            } else {
                return AjaxResult.success(StoreOrderStatusEnum.refund_on.name());
            }
        } else if (paymentMethod.equals(PaymentMethodEnum.WECHAT.name())) {
            //todo 微信支付 待写
            order.setStatus("refund_success");
            orderMapper.updateById(order);
        } else {
            // todo 现金支付 待写
            order.setStatus("refund_success");
            orderMapper.updateById(order);
        }

        return AjaxResult.success();
    }

    @Transactional
    @Override
    public Long createOrder(BuyGoodsVo bgv) {
        if (bgv.getId() == null || bgv.getNum() == null || bgv.getReceiveAddressId() == null) {
            throw new RuntimeException("参数非法！");
        }
        Goods goods = goodsMapper.selectById(bgv.getId());
        long inventory = goods.getGoodsInventory() == null ? 0 : goods.getGoodsInventory();
        if (inventory - bgv.getNum() < 0) {
            throw new RuntimeException("库存不足！");
        }
        SysUser user = SecurityUtils.getLoginUser().getUser();
        goods.setGoodsInventory(inventory);
        goodsMapper.updateGoods(goods);
        Order order = new Order();
        order.setUserId(user.getUserId());
        order.setGoodsId(bgv.getId());
        order.setGoodsNum(bgv.getNum());
        order.setSpecifications(bgv.getSpecifications());
        order.setOrderNum("LYH" + CommonUtils.getRandom());
        order.setReceiveAddressId(bgv.getReceiveAddressId());
        order.setStatus(StoreOrderStatusEnum.wait_pay.name());
        if ("ASSET_EVIDENCE".equals(bgv.getType())) {
            order.setPrice(goods.getAssetEvidenceNum().multiply(new BigDecimal(bgv.getNum())));
            order.setActualPayment(goods.getAssetEvidenceNum().multiply(new BigDecimal(bgv.getNum())));
        } else {
            order.setPrice(goods.getPrice().multiply(new BigDecimal(bgv.getNum())));
            order.setActualPayment(goods.getPrice().multiply(new BigDecimal(bgv.getNum())));
        }
        order.setCreateTime(new Date());
        ReceiveAddress receiveAddress = receiveAddressMapper.selectById(order.getReceiveAddressId());
        StringBuffer sb = new StringBuffer();
        sb.append(receiveAddress.getAddress()).append(receiveAddress.getSpecificAddress());
        order.setLogisticsInfo(sb.toString());
        orderMapper.insert(order);
        return order.getId();
    }

    @Autowired
    private IPayBiz payBiz;

    @Autowired
    private RedissonClient redissonClient;

    @Override
    public AjaxResult pay(PayVo payVo) {
        if (payVo.getOrderId() == null || payVo.getPaymentMethod() == null) {
            throw new RuntimeException("参数异常！");
        }
        SysUser sysUser = sysUserMapper.selectById(SecurityUtils.getLoginUser().getUserId());
        String returnStr = null;
        Order order = orderMapper.selectById(payVo.getOrderId());
        Asset asset = assetMapper.selectAssetByUserId(order.getUserId());
        Goods goods = goodsMapper.selectById(order.getGoodsId());
        //加锁
        String key;
        if (goods.getGoodsClass() == 2) {
            key = "pay_order_store_id"; //门店只能一级级返
        } else if (goods.getGoodsClass() == 1) {
            key = "pay_order_member_id";
        } else {
            key = "pay_order_" + payVo.getOrderId();
        }

        RLock lock = redissonClient.getLock(key);
        try {
            if (lock.tryLock(30, 30, TimeUnit.SECONDS)) {
                //检查是否已支付
                if (!order.getStatus().equals(StoreOrderStatusEnum.wait_pay.name())) {
                    return AjaxResult.error("你的订单已支付，请稍后刷新下！");
                }
                if (ALIPAY.name().equals(payVo.getPaymentMethod())) {
                    //调用支付宝支付
                    GoodsInventoryDeal(order, goods);
                    order.setPaymentMethod(payVo.getPaymentMethod());
                    orderMapper.updateById(order);
                    returnStr = payBiz.zfbPay(order);
                } else if (WECHAT.name().equals(payVo.getPaymentMethod())) {
                    //月销加
                    order.setPayTime(new Date());
                    GoodsInventoryDeal(order, goods);
                } else if (SecurityUtils.matchesPassword(payVo.getPayPassword(), sysUser.getPayPassword())) {
                    AjaxResult x = noOnlinePay(payVo, sysUser, order, asset, goods);
                    if (x != null) {
                        return x;
                    }
                } else {
                    return AjaxResult.error("密码错误！");
                }
            }
        } catch (Exception e) {
            log.error("下单错误", e);
            throw new ServiceException(e.getMessage());
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }


        return AjaxResult.success(returnStr);
    }

    @Transactional(rollbackFor = Exception.class)
    public AjaxResult noOnlinePay(PayVo payVo, SysUser sysUser, Order order, Asset asset, Goods goods) {
        order.setPayTime(new Date());
        //添加收支记录
        OperationInfo info = new OperationInfo();
        info.setUserId(sysUser.getUserId());
        info.setStatus(OperationStatusEnum.EXPENSE.name());
        info.setOperationTime(new Date());
        info.setOrigin(OperationOriginEnum.BUG_GOODS.name());
        if (ASSET_EVIDENCE.name().equals(payVo.getPaymentMethod())) {
            BigDecimal multiply = goods.getAssetEvidenceNum().multiply(new BigDecimal(order.getGoodsNum()));
            if (asset.getAssetEvidenceNum().subtract(multiply).compareTo(new BigDecimal(0)) >= 0) {
                asset.setAssetEvidenceNum(asset.getAssetEvidenceNum().subtract(multiply));
                info.setType(OperationTypeEnum.ASSET_EVIDENCE.name());
                info.setPrice(multiply);
            } else {
                return AjaxResult.error("资产通证余额不足，请及时充值！");
            }

            assetMapper.updateById(asset);
            order.setPaymentMethod(payVo.getPaymentMethod());
            order.setStatus(StoreOrderStatusEnum.wait_send.name());
            orderMapper.updateById(order);
            operationInfoMapper.insert(info);

        } else if (CASH.name().equals(payVo.getPaymentMethod())) {
            if (asset.getAccountBalance().subtract(order.getActualPayment()).compareTo(new BigDecimal(0)) >= 0) {
                asset.setAccountBalance(asset.getAccountBalance().subtract(order.getActualPayment()));
                info.setType(OperationTypeEnum.CASH.name());
                info.setPrice(order.getActualPayment());

                assetMapper.updateById(asset);
                order.setPaymentMethod(payVo.getPaymentMethod());
                order.setStatus(StoreOrderStatusEnum.wait_send.name());
                orderMapper.updateById(order);
                operationInfoMapper.insert(info);
            } else {
                return AjaxResult.error("余额不足，请及时充值！");
            }
        } else if (INTEGRAL.name().equals(payVo.getPaymentMethod())) {
            BigDecimal bd = new BigDecimal(asset.getIntegral());
            if (bd.subtract(order.getActualPayment()).compareTo(new BigDecimal(0)) >= 0) {
                asset.setIntegral(bd.subtract(order.getActualPayment()).longValue());
                info.setType(OperationTypeEnum.INTEGRAL.name());
                info.setPrice(order.getActualPayment());
            } else {
                return AjaxResult.error("门店积分余额不足，请及时充值！");
            }

            assetMapper.updateById(asset);
            order.setPaymentMethod(payVo.getPaymentMethod());
            order.setStatus(StoreOrderStatusEnum.wait_send.name());
            orderMapper.updateById(order);
            operationInfoMapper.insert(info);
        } else if (CHANGES.name().equals(payVo.getPaymentMethod())) {
            BigDecimal changes = asset.getChanges();
            if (changes.subtract(order.getActualPayment()).compareTo(new BigDecimal(0)) >= 0) {
                asset.setChanges(changes.subtract(order.getActualPayment()));
                info.setType(OperationTypeEnum.CHANGES.name());
                info.setPrice(order.getActualPayment());
            } else {
                return AjaxResult.error("零钱余额不足，请及时充值！");
            }

            assetMapper.updateById(asset);
            order.setPaymentMethod(payVo.getPaymentMethod());
            order.setStatus(StoreOrderStatusEnum.wait_send.name());
            orderMapper.updateById(order);
            operationInfoMapper.insert(info);
        }
        //月销加
        monthSaleAdd(sysUser, order, goods);
        return null;
    }


    @Transactional
    public void monthSaleAdd(SysUser sysUser, Order order, Goods goods) {
        GoodsInventoryDeal(order, goods);
        //返佣
        orderBiz.orderRebate(order, sysUser);

    }

    //库存销量判断
    private void GoodsInventoryDeal(Order order, Goods goods) {
        if (goods.getMonthlySales() == null || goods.getMonthlySales() == 0) {
            goods.setMonthlySales(order.getGoodsNum());
        } else {
            goods.setMonthlySales(goods.getMonthlySales() + order.getGoodsNum());
        }
        //库存减
        if (goods.getGoodsInventory() == null || goods.getGoodsInventory() - order.getGoodsNum() < 0) {
            throw new RuntimeException("商品库存不足，请联系管理员补充！");
        } else {
            goods.setGoodsInventory(goods.getGoodsInventory() - order.getGoodsNum());
        }
        goodsMapper.updateById(goods);
    }

    //库存判断

}
